package cn.lhjl.day09.note;
/*
* 单例模式
* 1.懒汉模式：例子如下
*
*
*
package cn.lhjl.day09.单例模式.懒汉模式;

public class DanLi {
    private static DanLi danLi=null;
    private DanLi() {
    }
    public static DanLi getInstance(){
        if (danLi==null){
            danLi=new DanLi();
        }
        return danLi;
    }

}

* 线程不安全：可能会存在第一个线程刚刚判断完if语句还没开始创建对象，第二线程就开始if判断，并且
* 进入引用数据类型是空的那个新建对象分支。最后导致创建了两个对象（线程越多重复越多）
*
* 补充知识点：在红色断点处点击右键，选择Thread。我们可以控制cpu选择线程，不再随机，从而找出多线程
* 可能存在的问题。
*
* 解决懒汉式单例模式线程不安全的方法：
* 1.给getInstance方法加锁，静态方法锁，锁的对象为这个单例类的.class对象。但是这种方法性能不好
* 2.双重验证模式 示例如下
package cn.lhjl.day09.单例模式.懒汉模式;

public class DanLi {
    private volatile static DanLi danLi = null;

    private DanLi() {
    }

    public  static  DanLi getInstance() {
        if (danLi == null) {
            synchronized (DanLi.class) {
                if (danLi==null){
                    danLi = new DanLi();
                }
            }
        }
        return danLi;
    }

}
*
* 只在danLI为null的分支设置锁，这样在对象已经创建完毕的情况下，线程都不会阻塞，
* 之所以要设置两个if，是因为一起进第一个if的有很多线程，但是只需要让一个线程去new，其他的等着，当去new的那个线程
* new结束后，释放锁，这是danLI已经变不为null了，那些进入到第一个if的线程这时通过第二个if后就returen danli了。
* 之所以要给成员变量danLi加上修饰符volatile，是为了让danLi看不到对象初始化重排序（了解即可）
*
* 3.基于静态内部类特性的单例模式
* 实例：
package cn.lhjl.day09.单例模式.懒汉模式;

public class InnerDanLi {
    private static class Innerclass{
        private static InnerDanLi innerDanLi = new InnerDanLi();
    }
    public InnerDanLi getInstance(){
        return Innerclass.innerDanLi;
    }
}

*
* 静态内部类在外部类加载时是不会被加载的，只有当用户调用了外部类的getInstance方法，它才被加载。这时静态变量
* innerDanLi才被赋值，因为类加载只会执行一次，所以即使是多线程，也只会有一个线程在内部类中new。
*
*
* 2.懒汉模式：
* 在类中直接设置一个静态成员变量，并且不为null，指向new这个类产生的对象。
* 好处：写法简单，用类之加载一次这个特性让线程安全
* 缺点：不管main中需不需创建这个类的对象，这个类一加载，就会创建对象，可能会浪费内存空间。
* */
public class 单例模式 {

}
